//^v^v^v^v^v^v^v^v^v^ Map v^v^v^v^v^v^v^v^v^v^v^v
class map //: IShaderConstantSetCallBack
{
	IAnimatedMesh				BSP;	//Level BSP Map
	ITerrainSceneNode			Trn;	//Map Terrain SceneNode
	ITexture					Hgt;	//Terrain Height Map
	ITexture					Dtl;	//Detail Map
	ITexture					Nrm;	//Light Map
	list						Mat;	//Terrain Brush Material
	ISceneNode					Nde;	//Map SceneNode
	vector3df					Grv;	//Level Gravity
	ITriangleselector			Slc;	//Map Triangle Selector
	SLight						Lgt;	//Global Light Source

public:
//Map Attributes
	aabbox3df                   OpnPth; //AI Pathnodes
	float						scale;	//*?
	float						scale2;	//*?

	//virtual void OnSetConstants( IMaterialRendererServices* services, s32 userData )
	//{
	//	int		d[]	=
	//		{0, 1, 2, 3};		//Sampler2d IDs
	//
	//	IVideoDriver*	VideoDriver		= services->getVideoDriver();
	//	matrix4			worldViewProj	= VideoDriver->getTransform( ETS_PROJECTION );
	//	worldViewProj	*= VideoDriver->getTransform( ETS_VIEW );
	//	worldViewProj	*= VideoDriver->getTransform( ETS_WORLD );
	//
	//	services->setVertexShaderConstant( "mat", worldViewProj.pointer(), 16 );
	//	services->setVertexShaderConstant( "SunPosPreT", &SunPos.X, 3 );
	//	services->setVertexShaderConstant( "MoonPosPreT", &MoonPos.X, 3 );
	//	services->setVertexShaderConstant( "max_sun_height", &MaxSunHeight, 1 );
	//	services->setPixelShaderConstant( "MaxD", &FarLink, 1 );
	//	services->setPixelShaderConstant( "s", &scale, 1 );
	//	services->setPixelShaderConstant( "s2", &scale2, 1 );
	//	services->setPixelShaderConstant( "sunDiffuse", &SunDiffuse.r, 4 );
	//	services->setPixelShaderConstant( "Tex", ( float* )&d[0], 1 );
	//	services->setPixelShaderConstant( "Tex2", ( float* )&d[1], 1 );
	//}
	
	map( stringw, stringw, vector3df, stringw, stringw, stringw, ILightSceneNode, vector3df );

	Update( map M )
	{
		return 1;
	};

	~map();

private:
	list	Cnt;	//Map Count
};
map::map( stringw MNam, stringw MBSP, vector3df MGrv, stringw MHgt, stringw MDtl, stringw MTex, ILightSceneNode MLgt, vector3df MSca )
{
	ISceneUserDataSerializer	*mapdata;

	smgr->loadScene( "\media\map" + MapNam + ".irr", &mapdata );

	//Build BSP Mesh
	if(	MBSP )
	{
		device->getFileSystem()->addZipFileArchive( "media\maps.pk3" );
		this->BSP	= smgr->getMesh( MBSP )->getMesh( 0 );	//Map Mesh
	}

	//Terrain HeightMap
	if(	MHgt )
	{
		this->Hgt	= MHgt;
		this->Trn	= smgr->addTerrainSceneNode(
			this->Hgt,								// heightmap
			0,										// parent node
			-1,										// node id
			vector3df( -100.f,    0.f, -100.f ),	// position
			vector3df(    0.f,    0.f,    0.f ),	// rotation
			vector3df(   40.f,    5.f,   40.f ),	// scale
			SColor( 255, 255, 255, 255 ),			// vertexColor
			5,										// maxLOD
			ETPS_17,								// patchSize
			4 );									// smoothFactor

		<s32>	DetailMap	= driver->getGPUProgrammingServices()->addHighLevelShaderMaterialFromFiles( "./shaders/DTMV.glsl", "vertexMain", EVST_VS_2_0, "./shaders/DTMP.glsl", "pixelMain", EPST_PS_2_0, DTM, EMT_SOLID );
		this->Trn->setMaterialTexture( 0, driver->getTexture( Tex ));
		this->Trn->setMaterialTexture( 1, driver->getTexture( Dtl ));
		this->Trn->setMaterialTexture( 2, driver->getTexture( Nrm ));
		this->Trn->getMaterial( 1 )setMaterialType( EMT_DETAIL_MAP );
		this->Trn->getMaterial( 2 )setMaterialType( EMT_NORMAL_MAP_SOLID);
		this->Trn->setMaterialFlag( EMF_LIGHTING, false );
		this->Trn->getMaterial( 2 )setMaterialFlag( EMF_LIGHTING, true );
		this->Trn->getMaterial( 0 ).AmbientColor = SColor( 255, 55, 55, 55 );
		this->Trn->scaleTexture( 1.0f, 20.0f );
	}

	//Include Global Light Source
	this->Lgt.Type = ELT_DIRECTIONAL;	//Light Type
	ILightSceneNode::setLightData( this->Lgt );

	//Paint Terrain Material Brushes
	Mat = MMat;
	
	//Check Map Mesh
	if(	this->BSP.IsValid())
		this->Nde	= smgr->addOctTreeSceneNode( MBSP.getMesh( 0 ));

	if(	this->Nde.IsValid())
	{
		this->Nde.SetPosition( vector3df( 0, 0, 0 ));

		this->Slc	= smgr->createOctTreeTriangleselector( this->BSP.getMesh( 0 ), this->Nde, 128 );
		this->Nde.setTriangleselector( this->Slc );
	}

	//Create Object Scene Types
	list	Obj	= ISceneManager::getRootSceneNode()::getChildren();
	
	for each( ISceneNode Tpe in list Obj )
	{
		IAttributes A = Tpe;

		//Check Type
		switch( A.getAttributeType( "type" ).getAttributeasString())
		{
		    case "backdrop":
                backdrop( S,
                    S.getAttributeName( "name" ),
                    S.getAttributeName( "hazard" ),
                    S.getAttributeName( "clip" ),
                    S.getAttributeName( "sway" ),
                    S.getAttributeName( "health" ),
                    S.getAttributeName( "state" ),
                    null,
                    S.getAttributeasArray( "animation" ); //*Incomplete Animation Table
                    break;
            case "water":
                water( S,
                    S.getAttributeName( "name" ),
                    S.getAttributeName( "state" ),
                    S.getAttributeName( "texture" ),
                    S.getAttributeName( "splash" ),
                    S.getAttributeName( "current" ));
                    break;
		    case "wind":
                wind( S,
                    S.getAttributeName( "name" ),
                    S.getAttributeName( "state" ),
                    S.getAttributeName( "velocity" ));
                    break;
		    case "ladder":
                ladder( S,
                    S.getAttributeName( "name" ),
                    S.getAttributeName( "state" ),
                    S.getAttributeName( "direction" ),
                    S.getAttributeName( "radius" ));
                    break;
		    case "prop":
                prop( S,
                    S.getAttributeName( "name" ),
                    S.getAttributeName( "state" )
                    S.getAttributeName( "velocity" )
                    S.getAttributeasArray( "animation" )); //*Incomplete Animation Table
		    case "door":
                door( S,
                    S.getAttributeName( "name" ),
                    S.getAttributeName( "state" ),
                    S.getAttributeName( "switch" ),
                    S.getAttributeName( "trigger" ),
                    S.getAttributeasArray( "animation" )); //*Incomplete Animation Table
                    break;
		    case "elevator":
				elevator( S,
					S.getAttributeName( "name" ),
					S.getAttributeName( "state" ),
					S.getAttributeName( "pointa" ),
					S.getAttributeName( "pointb" ),
					S.getAttributeName( "path" ),
					S.getAttributeName( "speed" ))
		    case "conveyor":
				conveyor( S,
					S.getAttributeName( "name" ),
					S.getAttributeName( "state" ),
					S.getAttributeName( "speed" ))
		    case "spawn":
		    case "trigger":
                trigger( S,
                    S.getAttributeName( "name" ),
                    S.getAttributeName( "state" ),
                    S.getAttributeName( "type" ),
					S.getAttributeName( "style" ),
					S.getAttributeName( "Lock" ),
					S.getAttributeName( "delay" ),
					S.getAttributeName( "timmer" ),
					S.getAttributeName( "prop" ));
		    case "portal":
				portal( S,
					S.getAttributeName( "light" ),
					S.getAttributeName( "sound" );
		    case "effect":
				effect( S,
					S.getAttributeName( "name" ),
					S.getAttributeName( "life" ),
					S.getAttributeName( "state" ));
		    case "collectable":
				collectable( S,
					S.getAttributeName( "name" ),
					S.getAttributeName( "animation" ),
					S.getAttributeName( "style" ),
					S.getAttributeName( "amount" ),
					S.getAttributeName( "hazard" );
			case "entity":
				entity( S.getAttributeName( "name" ),
					S.getAttributeName( "mesh" ),
					S,
					S.getAttributeName( "ellipsoid" ),
					S.getAttributeName( "state" ),
					S.getAttributeName( "event" ),
					S.getAttributeName( "health" ),
					S.getAttributeArray( item[]),
					S.getAttributeArray( weapon[]));
		    default: continue;  //Invalid Syntax
		}
	}
	
	return this;
};
map::~map()
{
	map::Cnt.erase( this );

	return this;
};
